home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 22
/
Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso
/
Aminet
/
util
/
cdity
/
VesaDPMSPro.lha
/
VesaDPMSPro
/
VESADPMS.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-10-19
|
38KB
|
1,646 lines
/*
*********** You need a tabulator width of 3 for a neat display !!! ***********
* *
* VESADPMS - Powersaving for VESA-compliant monitors and graphics cards *
* *
* Why another one ? Maybe, VESA didn't make themselves too clear in their *
* DPMS proposals. As an effect, my gfx-card/monitor combination has a basic *
* misinterpretation of the order, in which the blanking phases should come *
* up. The suspend command switches off, and the off command suspends... *
* *
* Sadly, at this time no blanker supports a user-defined order of blanking. *
* Even MCP, where you can set the absolute blanking times, doesn't work for *
* some strange reason. *
* *
* This blanker allows free combinations of the blanking order, to solve this *
* problem. It should work with any CyberGraphX gfx-card and monitor suppor- *
* ting DPMS. *
* *
* Thanks must go to: Magnus Holmgren - for CGXDPMS *
* Stefan Sommerfeld/Michael Knoke - for MCP *
* *
* I hereby state, that VesaDPMS is NOT a rip-off of any of these or another *
* DPMS blanker. No stolen code, maybe some inspiration. Apart from that, the *
* included source code to CGXDPMS didn't convince me that much (the code for *
* the custom CxObj is too large and unnecessarily calls some OS functions, *
* even one Intuition function, which is explicitly forbidden in the RKM !). *
* *
* WARNING: This source code is for explanatory/tutorial purpose only !!! *
* Don't try to compile it with any C-Compiler, it won't work. The *
* reason for this are my currently unreleased private C programming *
* support functions, that allow fast, but functional programming of *
* applications. They are not finished yet, maybe I will never re- *
* lease them, even if they are finished. It took me too much work *
* to just give them away freely ... *
* *
******************************************************************************
*/
#include <pragma/exec_lib.h>
#include <pragma/dos_lib.h>
#include <pragma/intuition_lib.h>
#include <pragma/gadtools_lib.h>
#include <pragma/graphics_lib.h>
#include <pragma/commodities_lib.h>
#include <pragma/icon_lib.h>
#include <pragma/utility_lib.h>
#include <pragma/cybergraphics_lib.h>
#include <clib/macros.h>
#include <intuition/intuitionbase.h>
#include <intuition/gadgetclass.h>
#include <cybergraphics/cybergraphics.h>
#include <stdlib.h>
#include <string.h>
#include <standardfuncprotos.h>
#define CUSTOM_ID 'CUST'
#define SENDER1_ID 'SND1'
#define SENDER2_ID 'SND2'
/********** Program parameter description **********/
struct Pref
{
struct Screen *screen; /* Screen from which to lend a ViewPort */
struct MsgPort *cxport; /* Message port for commodities communication */
ULONG standby; /* Seconds until entering standby mode */
ULONG suspend; /* Seconds until entering syspend mode */
ULONG off; /* Seconds until entering off mode */
ULONG priority; /* Priority of the Broker CxObject */
ULONG wakeup; /* InputEvent classes, that wake up from blanking */
ULONG dpmslevel; /* Current state of DPMS level */
ULONG signal; /* Signal for Custom CxObj, to indicate user activity */
char *popkey; /* User interface popup event combination */
char *blankkey; /* Immediate blank event combination */
};
struct newPref
{
ULONG standby; // Seconds until entering standby mode
ULONG suspend; // Seconds until entering suspend mode
ULONG off; // Seconds until entering off mode
UBYTE check_standby; // Standby mode enabled ?
UBYTE check_suspend; // Suspend mode enabled ?
UBYTE check_off; // Off mode enabled ?
UBYTE mouse; // Mouse wakes up ?
UBYTE disk; // Disk wakes up ?
UBYTE tablet; // Tablet wakes up ?
UBYTE key; // unused, intended for keystroke
UBYTE swtch; // Screen switching allowed ?
char *popkey; // Key combination to pop up interface
char *blankkey; // Key combination for immediate blanking
};
/********** Global variables **********/
//Global pointers
extern struct IntuitionBase *IntuitionBase;
struct Library *CyberGfxBase = NULL;
CxObj *broker = NULL;
// Special macro for standard version string with MaxonDev4.0
char *ver = AMIGAVERSION("VESADPMS", "1.2");
// ReadArgs stuff
char *ratmpl = "CX_PRIORITY/N,CX_POPUP/T,PREFS=PREFERENCES/K";
LONG arg[3] = {0, 1, 0};
char preffile[128] = "SYS:Prefs/Presets/VesaDPMS.prefs";
// Custom CxObj signalling facilities
ULONG lastsig = 0;
ULONG listen = ((1 << IECLASS_RAWKEY) | (1 << IECLASS_RAWMOUSE) | (1 << IECLASS_DISKINSERTED) | \
(1 << IECLASS_DISKREMOVED) | (1 << IECLASS_NEWPOINTERPOS));
BOOL active = FALSE, switchscreen = FALSE;
// Cluster of the program preferences variables, for easy usage
struct Pref prefs =
{
NULL,
NULL,
300,
600,
900,
0,
// Support keypress, mousemove, diskchange and graphic tablet
((1 << IECLASS_RAWKEY) | (1 << IECLASS_RAWMOUSE) | (1 << IECLASS_DISKINSERTED) | \
(1 << IECLASS_DISKREMOVED) | (1 << IECLASS_NEWPOINTERPOS)),
DPMS_ON,
~0,
NULL, // MUST be allocated by allocPVec()
NULL // dito
};
// To be filled in after argument parsing !
struct newPref temp;
struct IBox winbox = {0, 11, 0, 0};
// Font for the interface gadgets. Must be global. And, no, it's not hardcoded "topaz 8", that's
// just for some useful initialization !
char fontname[32] = "topaz.font";
struct TextAttr ta =
{
fontname,
8,
FS_NORMAL,
0
};
// Remember the gadget addresses for keyboard shortcut handling
#define INT_1_ID 0
#define INT_2_ID 1
#define INT_3_ID 2
#define CB_1_ID 3
#define CB_2_ID 4
#define CB_3_ID 5
#define CB_4_ID 6
#define CB_5_ID 7
#define CB_6_ID 8
#define CB_7_ID 9
#define STR_1_ID 10
#define STR_2_ID 11
struct Gadget *gg[12];
/********** Application strings ready for localizing (one day ...) **********/
#define TERMINATOR 0
#define OPENCGXLIB 1
#define OPENxxxLIB 2
#define MEMORYPOOL 3
#define NBNAME 4
#define NBTITLE 5
#define NBDESCR 6
#define SIGNALLING 7
#define EVENTS 8
#define BLANKSCREEN 9
#define NOTCYBER 10
#define TICKER 11
#define NOPARMS 12
#define YESNO 13
#define OK 14
#define NUMBER1 15
#define NUMBER2 16
#define NUMBER3 17
#define CHECKBOX1 18
#define CHECKBOX2 19
#define CHECKBOX3 20
#define CHECKBOX4 21
#define STRING1 22
#define STRING2 23
#define BUTTON1 24
#define BUTTON2 25
#define BUTTON3 26
#define BUTTON4 27
#define REALLYQUIT 28
#define QUITCANCEL 29
#define STILLWRONG 30
#define LONGPATH 31
#define CORRUPTPREFS 32
#define WRITEERROR 33
#define DEFPOPKEY 34
#define DEFBLANKKEY 35
char *string[] =
{
"Program terminated !\n",
"Could not open \"cybergraphics.library\".\n",
"Need an Amiga with OS 3.0 or better.\n",
"Not enough memory.\n",
"VesaDPMS Pro V1.2",
"VesaDPMS",
"Flexible Monitor Power Management",
"Could not establish message system.\n",
"Could not link into event handling.\n",
"Could not lock Default Public Screen.\n",
"Default Public Screen is not a CyberGraphX screen.\n",
"Could not set up \"timer.device\".\n",
"You did not set valid blanking intervals.\nOne of them must be at least 10 sec.\nDo you want to correct them ?",
"Yes, show interface|No, exit",
"««« OK »»»",
"St_andby :",
"Susp_end :",
"_Off :",
"_Mouse :",
"_Disk :",
"_Tablet:",
"S_witch:",
"_Popkey :",
"_Blankkey:",
"_Quit",
"_Save",
"_Use",
"_Cancel",
"Do you really want to quit ?",
"Quit|Cancel",
"The blanking intervals you selected\nare still wrong !\n\nSelect OK to quit the program and\nREAD THE DOCUMENTATION !!!",
"The path for the preferences file is too long !\nIt must have less than 128 characters.\nI'm using defaults !",
"The preferences file is corrupt !\nCheck your settings and save again.\nI'm using defaults !",
"The preferences file could not be saved !\nThe path you supplied must be valid.\nAbout 2 kByte must be free on disk.",
"ctrl v",
"ctrl b",
NULL
};
/********** Prototypes of external functions **********/
void cx_custom_func(void);
/********** Prototypes of local functions **********/
BOOL basicsetup(void);
void basicshutdown(void);
void arguments(struct WBStartup *wbstartup);
BOOL extendedsetup(void);
void extendedshutdown(void);
BOOL showGUI(void);
void waitforblank(void);
BOOL startrequests(ULONG offset);
struct Window *setupwindow(void);
void shutdownwindow(struct Window *w);
BOOL handlewinevents(struct IntuiMessage *imsg, BOOL *toggle);
void settemp(void);
void usetemp(struct Window *w);
void savetemp(struct Window *w);
BOOL newhotkey(void);
void loadprefs(char *file);
void saveprefs(char *file);
/********** Main function **********/
void main(LONG argc, char **argv)
{
if(basicsetup())
{
arguments(argc ? NULL : (struct WBStartup *) argv);
if(extendedsetup())
{
waitforblank();
}
extendedshutdown();
}
basicshutdown();
exit(RETURN_OK);
}
/********** Local functions **********/
BOOL basicsetup(void)
{
register ULONG libs = MODULES | COMMODITY;
CyberGfxBase = OpenLibrary("cybergraphics.library", 40);
if(CyberGfxBase)
{
setminversion(39);
if(openlibs(libs) == libs)
{
if(createMemPool(1024))
{
return(TRUE);
}
else
{
PutStr(string[MEMORYPOOL]);
}
}
else
{
PutStr(string[OPENxxxLIB]);
}
}
else
{
PutStr(string[OPENCGXLIB]);
}
PutStr(string[TERMINATOR]);
return(FALSE);
}
void basicshutdown(void)
{
CloseLibrary(CyberGfxBase);
closelibs(ALL_LIBS);
}
void arguments(struct WBStartup *wbstartup)
{
register struct RDArgs *rdargs;
register struct DiskObject *dop;
register UBYTE *cp, **tt;
register LONG val;
if(wbstartup)
{
dop = openIcon(nextIcon(wbstartup));
if(dop)
{
tt = (UBYTE **) dop->do_ToolTypes;
cp = FindToolType(tt, "CX_PRIORITY");
if(cp)
{
if(StrToLong(cp, &val) > (LONG) 0)
{
prefs.priority = (ULONG) val;
}
}
cp = FindToolType(tt, "CX_POPUP");
if(cp)
{
arg[1] = (LONG) (Stricmp(cp, "yes") ? FALSE : TRUE);
}
cp = FindToolType(tt, "PREFERENCES");
if(cp)
{
if(astrlen(cp) < 128)
{
strcpy(preffile, cp);
}
else
{
// Show errormessage and pop up
infomessage(NULL, string[NBNAME], string[LONGPATH], string[OK]);
arg[1] = TRUE;
}
}
closeIcon(dop);
}
}
else
{
rdargs = ReadArgs(ratmpl, arg, NULL);
if(rdargs)
{
if(arg[0]) // CX_PRIORITY
{
prefs.priority = *((LONG *) arg[0]);
}
// arg[1] (CX_POPUP) is a BOOL
if(arg[2]) // PREFERENCES
{
if(astrlen((char *) arg[2]) < 128)
{
strcpy(preffile, (char *) arg[2]);
}
else
{
// Show errormessage and pop up
infomessage(NULL, string[NBNAME], string[LONGPATH], string[OK]);
arg[1] = TRUE;
}
}
FreeArgs(rdargs);
}
else
{
PrintFault(IoErr(), NULL);
}
}
loadprefs(preffile);
if(prefs.standby)
{
prefs.standby = MAX(prefs.standby, 10);
}
if(prefs.suspend)
{
prefs.suspend = MAX(prefs.suspend, 10);
}
if(prefs.off)
{
prefs.off = MAX(prefs.off, 10);
}
if(!prefs.popkey)
{
prefs.popkey = allocPVec(astrlen(string[DEFPOPKEY]) + 1);
if(prefs.popkey)
{
strcpy(prefs.popkey, string[DEFPOPKEY]);
}
}
if(!prefs.blankkey)
{
prefs.blankkey = allocPVec(astrlen(string[DEFBLANKKEY]) + 1);
if(prefs.blankkey)
{
strcpy(prefs.blankkey, string[DEFBLANKKEY]);
}
}
settemp();
}
BOOL extendedsetup(void)
{
prefs.screen = LockPubScreen(NULL);
if(!prefs.screen)
{
PutStr(string[BLANKSCREEN]);
return(FALSE);
}
if(!IsCyberModeID(GetVPModeID(&(prefs.screen->ViewPort))))
{
PutStr(string[NOTCYBER]);
return(FALSE);
}
prefs.signal = AllocSignal(~0);
prefs.cxport = CreateMsgPort();
if((!prefs.cxport) || (prefs.signal == ~0))
{
PutStr(string[SIGNALLING]);
return(FALSE);
}
if(newhotkey())
{
return(TRUE);
}
PutStr(string[EVENTS]);
return(FALSE);
}
void extendedshutdown(void)
{
register struct Message *msg;
FreeSignal(prefs.signal);
prefs.signal = ~0;
DeleteCxObjAll(broker);
broker = NULL;
if(prefs.cxport)
{
do
{
msg = GetMsg(prefs.cxport);
if(msg)
{
ReplyMsg(msg);
}
}
while(msg);
}
DeleteMsgPort(prefs.cxport);
prefs.cxport = NULL;
UnlockPubScreen(NULL, prefs.screen);
}
BOOL showGUI(void)
{
struct Window *win;
register struct IntuiMessage *imsg;
register CxObj *msg;
ULONG rcvd, wait = SIGBREAKF_CTRL_C;
BOOL go = TRUE, rw = TRUE;
win = setupwindow();
if(!win)
{
return(FALSE);
}
wait |= (1 << win->UserPort->mp_SigBit);
wait |= (1 << prefs.cxport->mp_SigBit);
while(go)
{
rcvd = Wait(wait);
if(rcvd & SIGBREAKF_CTRL_C)
{
go = FALSE;
rw = FALSE;
}
if(rcvd & (1 << win->UserPort->mp_SigBit)) // Window event
{
do
{
imsg = GT_GetIMsg(win->UserPort);
if(imsg)
{
go = handlewinevents(imsg, &rw);
if(!rw)
{
// If the Quit gadget was clicked, exit immediately and leave all
// pending messages to closeWindowSafely()
imsg = NULL;
}
}
}
while(imsg);
}
if(rcvd & (1 << prefs.cxport->mp_SigBit))
{
do
{
msg = (CxObj *) GetMsg(prefs.cxport);
if(msg)
{
if(CxMsgType(msg) == CXM_COMMAND)
{
switch(CxMsgID(msg))
{
case CXCMD_DISABLE:
{
active = FALSE;
ActivateCxObj(broker, active);
}
break;
case CXCMD_ENABLE:
{
active = TRUE;
ActivateCxObj(broker, active);
}
break;
case CXCMD_KILL:
{
rw = FALSE; // Leave program
}
case CXCMD_DISAPPEAR:
{
go = FALSE; // Leave GUI
}
default:
break;
}
}
ReplyMsg((struct Message *) msg);
}
}
while(msg);
}
}
shutdownwindow(win);
return(rw);
}
void waitforblank(void)
{
register struct ViewPort *vp;
register CxMsg *msg;
struct TagItem cgxtags[] =
{
{SETVC_DPMSLevel, DPMS_ON},
{TAG_END, 0}
};
ULONG sigrcvd, msgtyp, msg_id, ticksig;
ULONG sigwait = SIGBREAKF_CTRL_C, immediate;
BOOL go = TRUE;
ticksig = initTicker(UNIT_VBLANK);
if(!ticksig)
{
PutStr(string[TICKER]);
return;
}
sigwait |= ticksig;
sigwait |= (1 << prefs.cxport->mp_SigBit);
sigwait |= (1 << prefs.signal);
if(arg[1])
{
if(!showGUI())
{
closeTicker();
return;
}
}
if(!startrequests(0))
{
closeTicker();
return;
}
active = TRUE;
ActivateCxObj(broker, active);
// Pre-initialize with a guaranteed value for additional safety
vp = &(prefs.screen->ViewPort);
do
{
sigrcvd = Wait(sigwait);
if(sigrcvd & SIGBREAKF_CTRL_C)
{
go = FALSE;
}
if(sigrcvd & ticksig)
{
// Try to blank with the frontmost screen
vp = &(IntuitionBase->FirstScreen->ViewPort);
// If not, try the Default Public Screen
if(!IsCyberModeID(GetVPModeID(vp)))
{
// If switching screens is allowed, bring the Default PubScreen to front
// Note, that this is very irritating, when working on a different screen,
// so I make it an explicit switch to on.
if(switchscreen)
{
ScreenToFront(prefs.screen);
}
vp = &(prefs.screen->ViewPort);
}
switch(getUserData())
{
case DPMS_STANDBY:
{
cgxtags[0].ti_Data = DPMS_STANDBY;
CVideoCtrlTagList(vp, cgxtags);
prefs.dpmslevel = DPMS_STANDBY;
}
break;
case DPMS_SUSPEND:
{
cgxtags[0].ti_Data = DPMS_SUSPEND;
CVideoCtrlTagList(vp, cgxtags);
prefs.dpmslevel = DPMS_SUSPEND;
}
break;
case DPMS_OFF:
{
cgxtags[0].ti_Data = DPMS_OFF;
CVideoCtrlTagList(vp, cgxtags);
prefs.dpmslevel = DPMS_OFF;
}
default:
break;
}
}
if(sigrcvd & (1 << prefs.signal))
{
stopTicker(0);
if(prefs.dpmslevel != DPMS_ON)
{
cgxtags[0].ti_Data = DPMS_ON;
// Difficult to use "vp" again. But as the user didn't do anything until
// now (blanking was on, so the user was off), it should still be valid.
// 02/10/1997: This is definitely wrong ! If you use Commodores "Blanker"
// together with VesaDPMS and switch off mouse events, "vp" is trash !
// Thanks go to Stefan Hensen, for reporting the error !
vp = &(IntuitionBase->FirstScreen->ViewPort);
CVideoCtrlTagList(vp, cgxtags);
prefs.dpmslevel = DPMS_ON;
}
if(active)
{
go = startrequests(0);
}
}
if(sigrcvd & (1 << prefs.cxport->mp_SigBit))
{
do
{
msg = (CxMsg *) GetMsg(prefs.cxport);
if(msg)
{
msg_id = CxMsgID(msg);
msgtyp = CxMsgType(msg);
ReplyMsg((struct Message *) msg);
stopTicker(0);
if(prefs.dpmslevel != DPMS_ON)
{
cgxtags[0].ti_Data = DPMS_ON;
vp = &(IntuitionBase->FirstScreen->ViewPort);
CVideoCtrlTagList(vp, cgxtags);
prefs.dpmslevel = DPMS_ON;
}
switch(msgtyp)
{
case CXM_IEVENT:
{
switch(msg_id)
{
case SENDER1_ID: // POPKEY
{
active = FALSE;
ActivateCxObj(broker, active);
go = showGUI();
active = go;
ActivateCxObj(broker, active);
if(active)
{
go = startrequests(0);
}
}
break;
case SENDER2_ID: // BLANKKEY
{
// Find the shortest blanking time. Ignore zero values !
immediate = ~0;
if(prefs.standby)
{
immediate = MIN(immediate, prefs.standby);
}
if(prefs.suspend)
{
immediate = MIN(immediate, prefs.suspend);
}
if(prefs.off)
{
immediate = MIN(immediate, prefs.off);
}
if(immediate != ~0)
{
go = startrequests(immediate);
}
}
default:
break;
}
}
break;
case CXM_COMMAND:
{
switch(msg_id)
{
case CXCMD_APPEAR:
{
active = FALSE;
ActivateCxObj(broker, active);
go = showGUI();
active = go;
ActivateCxObj(broker, active);
if(active)
{
go = startrequests(0);
}
}
break;
case CXCMD_DISABLE:
{
active = FALSE;
ActivateCxObj(broker, active);
}
break;
case CXCMD_ENABLE:
{
go = startrequests(0);
active = TRUE;
ActivateCxObj(broker, active);
}
break;
case CXCMD_KILL:
{
go = FALSE; // Leave program loop
}
break;
case CXCMD_UNIQUE: // User tried to start us a second time: POPUP
{
active = FALSE;
ActivateCxObj(broker, active);
go = showGUI();
active = go;
ActivateCxObj(broker, active);
if(active)
{
go = startrequests(0);
}
}
default:
break;
}
}
default:
break;
}
}
}
while(msg);
}
}
while(go);
closeTicker();
active = FALSE;
ActivateCxObj(broker, active);
}
BOOL startrequests(ULONG offset)
{
BOOL ok = FALSE;
// Skip levels with blanking time set to zero seconds
if(prefs.standby)
{
ok |= startTicker(prefs.standby - offset, 0, DPMS_STANDBY);
}
if(prefs.suspend)
{
ok |= startTicker(prefs.suspend - offset, 0, DPMS_SUSPEND);
}
if(prefs.off)
{
ok |= startTicker(prefs.off - offset, 0, DPMS_OFF);
}
// Could any request be started ?
if(!ok)
{
// Is at least one time set ? Then it's an error !
if(prefs.standby || prefs.suspend || prefs.off)
{
PutStr(string[TICKER]);
}
else // Just a user's mistake
{
if(infomessage(NULL, string[NBNAME], string[NOPARMS], string[YESNO]))
{
ok = showGUI();
if((prefs.standby < 10) && (prefs.suspend < 10) && (prefs.off < 10))
{
infomessage(NULL, string[NBNAME], string[STILLWRONG], string[OK]);
ok = FALSE;
}
}
}
}
return(ok);
}
struct Window *setupwindow(void)
{
// Get tricky to save stack: fully initialize one taglist,
// then shorten the other ones: look at the TAG_MORE trick !
struct TagItem chktags1[] =
{
{GTCB_Checked, temp.check_standby},
{GTCB_Scaled, TRUE},
{GT_Underscore, (ULONG) '_'},
{TAG_END, 0}
};
struct TagItem chktags2[] =
{
{GTCB_Checked, temp.check_suspend},
{TAG_MORE, (ULONG) &chktags1[1]}
};
struct TagItem chktags3[] =
{
{GTCB_Checked, temp.check_off},
{TAG_MORE, (ULONG) &chktags1[1]}
};
struct TagItem chktags4[] =
{
{GTCB_Checked, temp.mouse},
{TAG_MORE, (ULONG) &chktags1[1]}
};
struct TagItem chktags5[] =
{
{GTCB_Checked, temp.disk},
{TAG_MORE, (ULONG) &chktags1[1]}
};
struct TagItem chktags6[] =
{
{GTCB_Checked, temp.tablet},
{TAG_MORE, (ULONG) &chktags1[1]}
};
struct TagItem chktags7[] =
{
{GTCB_Checked, temp.swtch},
{TAG_MORE, (ULONG) &chktags1[1]}
};
struct TagItem numtags1[] =
{
{GTIN_Number, temp.standby},
{GA_Disabled, FALSE},
{TAG_MORE, (ULONG) &chktags1[2]}
};
struct TagItem numtags2[] =
{
{GTIN_Number, temp.suspend},
{GA_Disabled, FALSE},
{TAG_MORE, (ULONG) &chktags1[2]}
};
struct TagItem numtags3[] =
{
{GTIN_Number, temp.off},
{GA_Disabled, FALSE},
{TAG_MORE, (ULONG) &chktags1[2]}
};
struct TagItem strtags1[] =
{
{GTST_String, (ULONG) temp.popkey},
{TAG_MORE, (ULONG) &chktags1[2]}
};
struct TagItem strtags2[] =
{
{GTST_String, (ULONG) temp.blankkey},
{TAG_MORE, (ULONG) &chktags1[2]}
};
struct TagItem *buttags = &chktags1[2];
struct NewGadget ng[16] =
{
{12, 1, 6, 2, string[NUMBER1], &ta, 1, PLACETEXT_LEFT, (APTR) INTEGER_KIND, numtags1},
{12, 3, 6, 2, string[NUMBER2], &ta, 2, PLACETEXT_LEFT, (APTR) INTEGER_KIND, numtags2},
{12, 5, 6, 2, string[NUMBER3], &ta, 3, PLACETEXT_LEFT, (APTR) INTEGER_KIND, numtags3},
{19, 1, 3, 2, NULL, &ta, 4, 0, (APTR) CHECKBOX_KIND, chktags1},
{19, 3, 3, 2, NULL, &ta, 5, 0, (APTR) CHECKBOX_KIND, chktags2},
{19, 5, 3, 2, NULL, &ta, 6, 0, (APTR) CHECKBOX_KIND, chktags3},
{32, 1, 3, 2, string[CHECKBOX1], &ta, 7, PLACETEXT_LEFT, (APTR) CHECKBOX_KIND, chktags4},
{32, 3, 3, 2, string[CHECKBOX2], &ta, 8, PLACETEXT_LEFT, (APTR) CHECKBOX_KIND, chktags5},
{32, 5, 3, 2, string[CHECKBOX3], &ta, 9, PLACETEXT_LEFT, (APTR) CHECKBOX_KIND, chktags6},
{32, 7, 3, 2, string[CHECKBOX4], &ta, 10, PLACETEXT_LEFT, (APTR) CHECKBOX_KIND, chktags7},
{12, 8, 10, 2, string[STRING1], &ta, 11, PLACETEXT_LEFT, (APTR) STRING_KIND, strtags1},
{12, 10, 10, 2, string[STRING2], &ta, 12, PLACETEXT_LEFT, (APTR) STRING_KIND, strtags2},
{24, 10, 11, 2, string[BUTTON1], &ta, 13, PLACETEXT_IN, (APTR) BUTTON_KIND, buttags},
{ 1, 13, 11, 2, string[BUTTON2], &ta, 14, PLACETEXT_IN, (APTR) BUTTON_KIND, buttags},
{13, 13, 11, 2, string[BUTTON3], &ta, 15, PLACETEXT_IN, (APTR) BUTTON_KIND, buttags},
{25, 13, 11, 2, string[BUTTON4], &ta, LASTGADGET, PLACETEXT_IN, (APTR) BUTTON_KIND, buttags}
};
struct IBox bevel[] =
{
{ 0, 0, 36, 15}, // Main box
{ 1, 7, 20, 0}, // Separate integer from string
{ 1, 12, 34, 0}, // Separate buttons from rest
{ 23, 9, 12, 0}, // Separate checkbox from button
{ 22, 1, 0, 10} // Separate left from right
};
struct Window *w;
struct Gadget *g;
ULONG flags = (WFLG_ACTIVATE | WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | \
WFLG_RMBTRAP | WFLG_SIMPLE_REFRESH);
ULONG idcmp = (IDCMP_REFRESHWINDOW | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY |\
BUTTONIDCMP | CHECKBOXIDCMP | INTEGERIDCMP | STRINGIDCMP);
UWORD x, y;
numtags1[1].ti_Data = temp.check_standby ? FALSE : TRUE;
numtags2[1].ti_Data = temp.check_suspend ? FALSE : TRUE;
numtags3[1].ti_Data = temp.check_off ? FALSE : TRUE;
// Get rid of "topaz 8", if you have set a better DefaultFont
getFontAttr(getDefFontSize(&x, &y), &ta);
g = layoutGadgets(prefs.screen, ng, x, y, 2, 2, 1, 1);
if(g)
{
w = openWin(string[NBNAME], flags, idcmp, prefs.screen, g, &winbox);
if(w)
{
gg[INT_1_ID] = ng[0].ng_UserData;
gg[INT_2_ID] = ng[1].ng_UserData;
gg[INT_3_ID] = ng[2].ng_UserData;
gg[CB_1_ID] = ng[3].ng_UserData;
gg[CB_2_ID] = ng[4].ng_UserData;
gg[CB_3_ID] = ng[5].ng_UserData;
gg[CB_4_ID] = ng[6].ng_UserData;
gg[CB_5_ID] = ng[7].ng_UserData;
gg[CB_6_ID] = ng[8].ng_UserData;
gg[CB_7_ID] = ng[9].ng_UserData;
gg[STR_1_ID] = ng[10].ng_UserData;
gg[STR_2_ID] = ng[11].ng_UserData;
bevelBox(w, &bevel[0], x, y, TRUE, BBFT_RIDGE);
bevelBox(w, &bevel[1], x, y, FALSE, BBFT_BUTTON);
bevelBox(w, &bevel[2], x, y, FALSE, BBFT_BUTTON);
bevelBox(w, &bevel[3], x, y, FALSE, BBFT_BUTTON);
bevelBox(w, &bevel[4], x, y, FALSE, BBFT_BUTTON);
return(w);
}
FreeGadgets(g);
}
return(NULL);
}
void shutdownwindow(struct Window *w)
{
struct Gadget *g = w->FirstGadget;
// Note: openWin() and closeWindowSafely() are automatically aware of shared
// window message ports. Too bad, I have not released them yet. ¦^)
removeBBox(w);
closeWindowSafely(w);
if(g)
{
FreeGadgets(g);
}
}
BOOL handlewinevents(struct IntuiMessage *imsg, BOOL *toggle)
{
register struct Window *win;
register struct Gadget *gad;
register ULONG class;
register UWORD code;
char *newpop, *newblank;
ULONG result;
BOOL rw = TRUE;
win = imsg->IDCMPWindow;
gad = imsg->IAddress;
class = imsg->Class;
code = imsg->Code;
GT_ReplyIMsg(imsg);
switch(class)
{
case IDCMP_GADGETUP:
{
switch(gad->GadgetID)
{
case 1: // Standby
{
GT_GetGadgetAttrs(gad, win, NULL, GTIN_Number, &result, TAG_END);
temp.standby = result;
}
break;
case 2: // Suspend
{
GT_GetGadgetAttrs(gad, win, NULL, GTIN_Number, &result, TAG_END);
temp.suspend = result;
}
break;
case 3: // Off
{
GT_GetGadgetAttrs(gad, win, NULL, GTIN_Number, &result, TAG_END);
temp.off = result;
}
break;
case 4: // CheckStandby
{
GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
GT_SetGadgetAttrs(gg[INT_1_ID], win, NULL, GA_Disabled, result ? FALSE : TRUE, TAG_END);
temp.check_standby = (UBYTE) result;
}
break;
case 5: // CheckSuspend
{
GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
GT_SetGadgetAttrs(gg[INT_2_ID], win, NULL, GA_Disabled, result ? FALSE : TRUE, TAG_END);
temp.check_suspend = (UBYTE) result;
}
break;
case 6: // CheckOff
{
GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
GT_SetGadgetAttrs(gg[INT_3_ID], win, NULL, GA_Disabled, result ? FALSE : TRUE, TAG_END);
temp.check_off = (UBYTE) result;
}
break;
case 7: // Mouse
{
GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
temp.mouse = (UBYTE) result;
}
break;
case 8: // Disk
{
GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
temp.disk = (UBYTE) result;
}
break;
case 9: // Tablet
{
GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
temp.tablet = (UBYTE) result;
}
break;
case 10: // Switch
{
GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
temp.swtch = (UBYTE) result;
}
break;
case 11: // Popkey
{
GT_GetGadgetAttrs(gad, win, NULL, GTST_String, &result, TAG_END);
if(stricmp((char *) result, temp.popkey))
{
newpop = allocPVec(strlen((char *) result) + 1);
if(newpop)
{
strcpy(newpop, (char *) result);
freePVec(temp.popkey);
temp.popkey = newpop;
}
}
}
break;
case 12: // Blankkey
{
GT_GetGadgetAttrs(gad, win, NULL, GTST_String, &result, TAG_END);
if(stricmp((char *) result, temp.blankkey))
{
newblank = allocPVec(strlen((char *) result) + 1);
if(newblank)
{
strcpy(newblank, (char *) result);
freePVec(temp.blankkey);
temp.blankkey = newblank;
}
}
}
break;
case 13: // Quit
{
*toggle = (infomessage(win, string[NBTITLE], string[REALLYQUIT], string[QUITCANCEL]) ? FALSE : TRUE);
rw = FALSE;
}
break;
case 14: // Save
{
if((prefs.popkey != temp.popkey) || (prefs.blankkey != temp.blankkey))
{
*toggle = newhotkey();
}
savetemp(win);
rw = FALSE;
}
break;
case 15: // Use
{
if((prefs.popkey != temp.popkey) || (prefs.blankkey != temp.blankkey))
{
*toggle = newhotkey();
}
usetemp(win);
rw = FALSE;
}
break;
case LASTGADGET: // Cancel
{
if(prefs.popkey != temp.popkey)
{
freePVec(temp.popkey);
}
if(prefs.blankkey != temp.blankkey)
{
freePVec(temp.blankkey);
}
settemp();
rw = FALSE;
}
default:
break;
}
}
break;
case IDCMP_REFRESHWINDOW:
{
GT_BeginRefresh(win);
drawBBox(win);
GT_EndRefresh(win, TRUE);
}
break;
case IDCMP_CLOSEWINDOW:
{
rw = FALSE;
}
break;
case IDCMP_VANILLAKEY:
{
switch(code | 32)
{
case TAB_KEY | 32:
{
ActivateGadget(gg[STR_1_ID], win, NULL);
}
break;
case 'a': // stAndby
{
GT_SetGadgetAttrs(gg[CB_1_ID], win, NULL, GTCB_Checked, TRUE, TAG_END);
GT_SetGadgetAttrs(gg[INT_1_ID], win, NULL, GA_Disabled, FALSE, GTIN_Number, temp.standby, TAG_END);
ActivateGadget(gg[INT_1_ID], win, NULL);
}
break;
case 'b': // Blankkey
{
ActivateGadget(gg[STR_2_ID], win, NULL);
}
break;
case 'c': // Cancel
{
if(prefs.popkey != temp.popkey)
{
freePVec(temp.popkey);
}
if(prefs.blankkey != temp.blankkey)
{
freePVec(temp.blankkey);
}
settemp();
rw = FALSE;
}
break;
case 'd': // Disk
{
temp.disk = temp.disk ? 0 : 1;
GT_SetGadgetAttrs(gg[CB_5_ID], win, NULL, GTCB_Checked, temp.disk, TAG_END);
}
break;
case 'e': // suspEnd
{
GT_SetGadgetAttrs(gg[CB_2_ID], win, NULL, GTCB_Checked, TRUE, TAG_END);
GT_SetGadgetAttrs(gg[INT_2_ID], win, NULL, GA_Disabled, FALSE, GTIN_Number, temp.suspend, TAG_END);
ActivateGadget(gg[INT_2_ID], win, NULL);
}
break;
case 'm': // Mouse
{
temp.mouse = temp.mouse ? 0 : 1;
GT_SetGadgetAttrs(gg[CB_4_ID], win, NULL, GTCB_Checked, temp.mouse, TAG_END);
}
break;
case 'o': // Off
{
GT_SetGadgetAttrs(gg[CB_3_ID], win, NULL, GTCB_Checked, TRUE, TAG_END);
GT_SetGadgetAttrs(gg[INT_3_ID], win, NULL, GA_Disabled, FALSE, GTIN_Number, temp.off, TAG_END);
ActivateGadget(gg[INT_3_ID], win, NULL);
}
break;
case 'p': // Popkey
{
ActivateGadget(gg[STR_1_ID], win, NULL);
}
break;
case 'q': // Quit
{
*toggle = (infomessage(win, string[NBTITLE], string[REALLYQUIT], string[QUITCANCEL]) ? FALSE : TRUE);
rw = FALSE;
}
break;
case 's': // Save
{
if((prefs.popkey != temp.popkey) || (prefs.blankkey != temp.blankkey))
{
*toggle = newhotkey();
}
savetemp(win);
rw = FALSE;
}
break;
case 't': // Tablet
{
temp.tablet = temp.tablet ? 0 : 1;
GT_SetGadgetAttrs(gg[CB_6_ID], win, NULL, GTCB_Checked, temp.tablet, TAG_END);
}
break;
case 'u': // Use
{
if((prefs.popkey != temp.popkey) || (prefs.blankkey != temp.blankkey))
{
*toggle = newhotkey();
}
usetemp(win);
rw = FALSE;
}
break;
case 'w': // sWitch
{
// Toggle SWITCHSCREENS
temp.swtch = temp.swtch ? 0 : 1;
GT_SetGadgetAttrs(gg[CB_7_ID], win, NULL, GTCB_Checked, temp.swtch, TAG_END);
}
default:
break;
}
}
break;
default:
break;
}
return(rw);
}
void settemp(void)
{
temp.standby = prefs.standby;
temp.suspend = prefs.suspend;
temp.off = prefs.off;
temp.check_standby = temp.standby ? 1 : 0;
temp.check_suspend = temp.suspend ? 1 : 0;
temp.check_off = temp.off ? 1 : 0;
temp.mouse = ((1 << IECLASS_RAWMOUSE) & prefs.wakeup) ? 1 : 0;
temp.disk = (((1 << IECLASS_DISKINSERTED) | (1 << IECLASS_DISKREMOVED)) & prefs.wakeup) ? 1 : 0;
temp.tablet = ((1 << IECLASS_NEWPOINTERPOS) & prefs.wakeup) ? 1 : 0;
temp.key = ((1 << IECLASS_RAWKEY) & prefs.wakeup) ? 1 : 0;
temp.swtch = switchscreen ? 1 : 0;
temp.popkey = prefs.popkey;
temp.blankkey = prefs.blankkey;
}
void usetemp(struct Window *w)
{
prefs.standby = temp.check_standby ? temp.standby : 0;
prefs.suspend = temp.check_suspend ? temp.suspend : 0;
prefs.off = temp.check_off ? temp.off : 0;
switchscreen = temp.swtch;
prefs.wakeup = (1 << IECLASS_RAWKEY);
prefs.wakeup |= temp.mouse ? (1 << IECLASS_RAWMOUSE) : 0;
prefs.wakeup |= temp.disk ? ((1 << IECLASS_DISKINSERTED) | (1 << IECLASS_DISKREMOVED)) : 0;
prefs.wakeup |= temp.tablet ? (1 << IECLASS_NEWPOINTERPOS) : 0;
prefs.wakeup |= temp.key ? (1 << IECLASS_RAWKEY) : 0;
prefs.popkey = temp.popkey;
prefs.blankkey = temp.blankkey;
// Finally remember the window position
snapshotwindow(w, &winbox);
// Leave sizing to layoutGadgets()
winbox.Width = 0;
winbox.Height = 0;
}
void savetemp(struct Window *w)
{
usetemp(w);
saveprefs(preffile);
}
// This function is for lazyness only. It's slower than only replacing the filter objects,
// but needs less code than an additional replacing function, that removes the old and
// inserts a new filter.
BOOL newhotkey(void)
{
CxObj *custom, *filter1, *filter2, *sender1, *sender2, *trans1, *trans2;
struct NewBroker nb =
{
NB_VERSION,
string[NBNAME],
string[NBTITLE],
string[NBDESCR],
NBU_UNIQUE | NBU_NOTIFY,
COF_SHOW_HIDE,
prefs.priority,
prefs.cxport,
0
};
DeleteCxObjAll(broker);
broker = CxBroker(&nb, NULL);
if(broker)
{
custom = CxCustom(&cx_custom_func, CUSTOM_ID);
filter1 = CxFilter(temp.popkey);
filter2 = CxFilter(temp.blankkey);
sender1 = CxSender(prefs.cxport, SENDER1_ID);
sender2 = CxSender(prefs.cxport, SENDER2_ID);
trans1 = CxTranslate(NULL);
trans2 = CxTranslate(NULL);
if(custom && filter1 && filter2 && sender1 && sender2)
{
// Here the single CxObjects are linked together. Note, that the custom CxObject
// directly Signal()s to the application to avoid additional overhead.
AttachCxObj(broker, custom); // +-> CUSTOM >---------------+
AttachCxObj(broker, filter1); // | |
AttachCxObj(broker, filter2); // BROKER >-+-> FILTER1 >-+-> SENDER1 >-+-> VesaDPMS
AttachCxObj(filter1, sender1); // | | |
AttachCxObj(filter2, sender2); // | (TRANS1/2) |
AttachCxObj(filter1, trans1); // | | |
AttachCxObj(filter2, trans2); // +-> FILTER2 >-+-> SENDER2 >-+
return(TRUE);
}
DeleteCxObj(trans2);
DeleteCxObj(trans1);
DeleteCxObj(sender2);
DeleteCxObj(sender1);
DeleteCxObj(filter2);
DeleteCxObj(filter1);
DeleteCxObj(custom);
DeleteCxObj(broker);
}
return(FALSE);
}
/*
Preferences structure: Standby time 4 bytes
Suspend time 4 bytes
Off time 4 bytes
CX_PRIORITY 4 bytes
Wakeup bits 4 bytes
Switch button state 2 bytes
X/Y window position 4 bytes
Length of popkey 4 bytes
Popkey variable length (0 - 256 bytes) !
Length of blankkey 4 bytes
Blankkey variable length (0 - 256 bytes) !
*/
void loadprefs(char *file)
{
register UBYTE *str, *oldpop;
register BPTR fh;
ULONG buffer[5];
ULONG size;
fh = Open(file, MODE_OLDFILE);
if(fh)
{
// Read in standby, suspend, off, priority and wakeup
if(FRead(fh, buffer, 4, 5) == 5)
{
// Read in Switch gadget state
if(FRead(fh, &switchscreen, 2, 1))
{
// Read in former window position
if(FRead(fh, &winbox, 4, 1))
{
// Read in size of popkey
if(FRead(fh, &size, 4, 1))
{
if(size > 256)
{
Close(fh);
infomessage(NULL, string[NBTITLE], string[CORRUPTPREFS], string[OK]);
return;
}
str = allocPVec(size);
if(str)
{
if(FRead(fh, str, size, 1))
{
oldpop = prefs.popkey;
prefs.popkey = str;
// Read in size of blankkey
if(FRead(fh, &size, 4, 1))
{
if(size > 256)
{
Close(fh);
infomessage(NULL, string[NBTITLE], string[CORRUPTPREFS], string[OK]);
prefs.popkey = oldpop;
return;
}
str = allocPVec(size);
if(str)
{
if(FRead(fh, str, size, 1))
{
freePVec(prefs.blankkey);
freePVec(oldpop);
prefs.blankkey = str;
CopyMem(buffer, &(prefs.standby), 20);
Close(fh);
return;
}
}
}
}
freePVec(str);
}
}
}
}
}
Close(fh);
infomessage(NULL, string[NBTITLE], string[CORRUPTPREFS], string[OK]);
prefs.popkey = oldpop;
}
}
void saveprefs(char *file)
{
register BPTR fh;
ULONG size;
fh = Open(file, MODE_NEWFILE);
if(fh)
{
if(FWrite(fh, &(prefs.standby), 4, 5) == 5)
{
if(FWrite(fh, &switchscreen, 2, 1))
{
if(FWrite(fh, &winbox, 2, 2) == 2)
{
size = astrlen(prefs.popkey) + 1;
if(FWrite(fh, &size, 4, 1))
{
if(FWrite(fh, prefs.popkey, size, 1))
{
size = astrlen(prefs.blankkey) + 1;
if(FWrite(fh, &size, 4, 1))
{
if(FWrite(fh, prefs.blankkey, size, 1))
{
Close(fh);
return;
}
}
}
}
}
}
}
}
Close(fh);
infomessage(NULL, string[NBTITLE], string[WRITEERROR], string[OK]);
}